﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace WeigherMoudel
{
    [ToolboxItem(false)]
    public partial class Weigher : UserControl
    {
        Form form;
        public ICommunication WeightCommunication;
        public RetWeight ContempWeight;
        internal DateTime lastupdatetime = new DateTime();
        internal bool issendClear = false;

        public bool IsFormShowType = true;

        public event Action<Weigher, RetWeight> WeightValueReceived;

        internal bool isgetStable = false;


        public FastData.VarSave<int> StableTimes;
        private bool connectionState = false;
        public bool ConnectionStatus
        {
            get
            {
                return connectionState;
            }
            set
            {
                if (connectionState == value) return;
                connectionState = value;
                if (!connectionState)
                    ContempWeight = null;
                ConnectionChanged?.Invoke(this, connectionState);
            }
        }


        private bool allowCommunicationSet=true;

        public bool AllowCommunicationSet
        {
            get { return allowCommunicationSet; }
            set { allowCommunicationSet = value; }
        }


        private string title = "";
        public event Action<Weigher, bool> ConnectionChanged;

        public string Title
        {
            get
            {

                return title;
            }
            set
            {
                title = value;
            }
        }

        public Weigher()
        {
            InitializeComponent();
        }

        public class RetWeight
        {
            internal RetWeight(bool isstable, string weight)
            {
                Weight = weight;
                IsStable = isstable;
            }

            internal RetWeight(bool isstable, string weight, float weightf)
            {
                Weight = weight;
                IsStable = isstable;
                WeightF = weightf;
            }
            public string Weight { get; }

            public float WeightF { get; }

            public bool IsStable { get; }

        }

        private void ANDweigh_Load(object sender, EventArgs e)
        {
            if (!IsDesignMode)
            {
                numericUpDown1.Value = StableTimes.Value;
            }
        }
        [Obsolete]
        public Weigher(NewSerialPortWeight serialport)
        {
            InitializeComponent();
            WeightCommunication = serialport;
            Name = WeightCommunication.Name;
            WeightCommunication.OnReceiveData += Weightserial_OnReceiveData;
          
        }

        [Obsolete]
        public Weigher(NewSerialPortWeight serialport,bool isFormShownType)
        {
            IsFormShowType = isFormShownType;
            InitializeComponent();
            WeightCommunication = serialport;
            Name = WeightCommunication.Name;
            WeightCommunication.OnReceiveData += Weightserial_OnReceiveData;

        }

        public virtual void  BeginCtor(string name)
        {


        }


        public Weigher(string name, bool isFormShownType, CommunicationType communicationType = CommunicationType.TCP)
        {
            Title = name;
            BeginCtor(name);
            IsFormShowType = isFormShownType;
            InitializeComponent();
            ICommunication communication = null;
            switch (communicationType)
            {
                case CommunicationType.SerialPort:
                    communication = new NewSerialPortWeight(name + "_And");
                    break;
                case CommunicationType.TCP:
                    communication = new NewTCP(name);
                    break;
                case CommunicationType.UDP:
                    communication = new NewUDP(name);
                    break;

            }
          
            StableTimes = new FastData.VarSave<int>("StableTimes_" + name);
            WeightCommunication = communication;
            Name = WeightCommunication.Name;
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Thread.Sleep(500);
                    try
                    {
                        if (!WeightCommunication.IsOpen )
                        {
                            WeightCommunication.Open(1);
                            //Console.WriteLine("Open");
                        }
                    }
                    catch(Exception EXP)
                    {
                    }
                    try
                    {
                        TimeSpan timeSpan = DateTime.Now - lastupdatetime;

                        if (timeSpan.TotalMilliseconds > 10000)//10秒不回复 掉线
                        {
                            ConnectionStatus = false;
                        }
                        else
                        {
                            ConnectionStatus = true;
                        }
                    }
                    catch { }
                }
            }, TaskCreationOptions.LongRunning);
            WeightCommunication.OnReceiveData += Weightserial_OnReceiveData;
        }


       


        internal virtual  void Weightserial_OnReceiveData(string obj)
        {

            //if (WeightValueReceived != null)
            //{
            //    Task.Factory.StartNew(() =>
            //    {
            //        WeightValueReceived?.Invoke(this, ContempWeight);
            //    }, TaskCreationOptions.LongRunning);
            //}
        }

        public virtual string PowerONCMD
        {
            get;
        }

        /// <summary>
        /// 开机
        /// </summary>
        /// <param name="time">等待时间</param>
        public void PowerON(int time)
        {
            if (WeightCommunication == null)
                return;
            if (WeightCommunication.IsOpen)
            {
                WeightCommunication.SendMessage(PowerONCMD);
                Thread.Sleep(time);   //停留5秒钟开机
            }
        }


        public bool IsPowerON()
        {
            if (GetWeightInstant(1000) == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }


        public virtual string PowerOFFCMD
        {
            get;
        }

        public void PowerOFF()
        {
            if (WeightCommunication == null)
                return;
            if (WeightCommunication.IsOpen)
                WeightCommunication.SendMessage(PowerOFFCMD);
        }

        /// <summary>
        /// 获得及时称重值
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public string GetWeightInstant(int timeout)
        {
            if (WeightCommunication == null)
                return null;
            return ContempWeight.Weight;
        }



        /// <summary>
        /// 获取稳定称重值
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public string GetWeightStable(int timeout)
        {
            try
            {
                isgetStable = true;
                //if (Weightserial == null || ContempWeight == null)
                //    return null;
                int c = 0;
                int stablelevel = 0;
                while (true)
                {
                    Thread.Sleep(100);
                    c++;
                    if (c > timeout / 100)
                    {
                        return null;
                    }
                    if (WeightCommunication == null || ContempWeight == null)
                    {
                        continue;
                    }
                    try
                    {
                        if (ContempWeight.IsStable)
                        {
                            stablelevel++;
                            if (stablelevel > StableTimes.Value)
                                return ContempWeight.Weight;
                        }
                        else
                        {
                            stablelevel = 0;
                        }
                    }
                    catch(Exception exp)
                    {

                    }
                }
            }
            finally
            {
                isgetStable = false;
            }
        }

        /// <summary>
        /// 清零-有超时（不建议使用）
        /// </summary>
        /// <param name="milliSenconds"></param>
        /// <returns></returns>
        /// 
        [Obsolete("方法已经过期")]
        public bool Zero(int milliSenconds)
        {
            int timeout = 0;
            if (WeightCommunication == null)
                return false;
            WeightCommunication.SendMessage(ZeroCMD);

            return true;

        }



        int isZero = 0;//0：正常状态  1：清零中  -1：清零失败
        private readonly object obj_zero_lock = new object();
        int zerovCount = 0;
        public int ZeroV(int timeout)
        {
            //Console.WriteLine("开事情零！");
            //if (zerovCount > 4)
            //{
            //    Console.WriteLine("开事情零》4次！");
            //    zerovCount = 0;
            //    return 0;
            //}
            //zerovCount++;
            //Console.WriteLine("开事情零！  "+ zerovCount );
            try
            {
                //485通讯双向可能失败，发送3次降低概率
                for (int i = 0; i < 10; i++)
                {
                    WeightCommunication.SendMessage(ZeroCMD);
                    Thread.Sleep(50);
                }
                //int unstableCount = 0;
                //while (true)
                //{
                //    //稳定在0.3之内
                //    if (ContempWeight.WeightF < 0.3f && ContempWeight.WeightF > -0.3f && ContempWeight.IsStable)
                //    {
                //        Console.WriteLine("清零成功！");
                //        unstableCount = 0;
                //        zerovCount = 0;
                //        break;
                //    }
                //    else
                //    {
                //        unstableCount++;
                //        if (unstableCount > 25)
                //        {
                //            Console.WriteLine("等待大于25次！");
                //            unstableCount = 0;
                //            ZeroV(timeout);
                //            break;
                //        }
                //    }
                //    Thread.Sleep(100);
                //}
                return 0;
            }
            catch
            {
                return 0;
            }
        }


        //public int ZeroV(int timeout)
        //{

        //    if (isgetStable) return 0;
        //    int s = 0;
        //    while (true)
        //    {
        //        if (!ContempWeight.IsStable)
        //        {
        //            Thread.Sleep(100);
        //            s++;
        //            if (s > timeout / 100)
        //            {
        //                return -1;
        //            }
        //        }
        //        else
        //        {
        //            break;
        //        }
        //    }

        //    issendClear = true;
        //    isZero = 1;
        //    if (WeightCommunication == null)
        //    {
        //        isZero = -1;
        //        return isZero;
        //    }
        //    try
        //    {
        //        WeightCommunication.SendMessage(ZeroCMD);
        //        Thread.Sleep(400);
        //    }
        //    catch
        //    {
        //        issendClear = false;
        //        isZero = -1;
        //        return isZero;
        //    }
        //    ContempWeight = null;
        //    issendClear = false;
        //    int c = 0;
        //    while (true)
        //    {
        //        if (ContempWeight != null)
        //        {
        //            isZero = 0;
        //            break;
        //        }
        //        if (!this.InvokeRequired)
        //        {
        //            Application.DoEvents();
        //        }
        //        Thread.Sleep(100);
        //        c++;
        //        if (c > timeout / 100)
        //        {
        //            isZero = -1;
        //            break;
        //        }
        //    }
        //    return isZero;
        //}

        public virtual string ZeroCMD
        {
            get;
        }


        private void btnSwitchOn_Click(object sender, EventArgs e)
        {
            PowerON(1000);
        }

        private void btnSwitchOff_Click(object sender, EventArgs e)
        {
            //PowerOFF();
        }

        private void btnRealTimeWeight_Click(object sender, EventArgs e)
        {
            //string ret = GetWeightInstant(1000);
            //if (!string.IsNullOrEmpty(ret))
            //    label6.Text = ret;
            //else
            //    label6.Text = "err";
        }

        private void btnStableTimeWeight_Click(object sender, EventArgs e)
        {
            textBox2.Text = "Waitting...";
            Application.DoEvents();
            string ret = GetWeightStable(3000);
            if (!string.IsNullOrEmpty(ret))
                textBox2.Text = ret;
            else
                textBox2.Text = "err";
        }

        private bool allowClear = true;
        public bool AllowClear
        {
            get
            {
                return allowClear;
            }
            set
            {
                allowClear = value;
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            if (allowClear)
                ZeroV(4000);
            else
                MessageBox.Show("当前不允许清零！");
        }

        private void btnSerialPortSetting_Click(object sender, EventArgs e)
        {
            Form form = new Form();
            form.AutoSize = true;
            form.Text = WeightCommunication.Name;
            form.Controls.Add(WeightCommunication as Control);
            form.FormClosing += new FormClosingEventHandler(form_FormClosing);
            form.ShowDialog();
        }

        private void form_FormClosing(object sender, FormClosingEventArgs e)
        {
            ((dynamic)sender).Controls.Clear();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                if (allowCommunicationSet)
                {
                    btnSerialPortSetting.Enabled = true;
                }
                else
                {
                    btnSerialPortSetting.Enabled = false;
                }


                if (allowClear)
                {
                    btnReset.Enabled = true;
                }
                else
                {
                    btnReset.Enabled = false;
                }
                label1.Text = title;
                if (ConnectionStatus)
                {
                    label8.Text = "在线";
                    label8.ForeColor = Color.Lime;

                }
                else
                {
                    label8.Text = "离线";
                    label8.ForeColor = Color.Red;
                    ContempWeight = null;

                }

                if (WeightCommunication != null)
                {
                  if(  WeightCommunication.Name== "前称1")
                    {

                    }
                    //label1.Text = "AND称重器" + $"({ANDserial.Name})";
                    if (WeightCommunication.IsOpen)
                    {
                        this.BackColor = Color.GreenYellow;
                        label5.Text = WeightCommunication.Setting.port + "-已打开";
                        if (isZero == 0)
                        {
                            if (ContempWeight == null)
                            {
                                label7.Text = " ";
                                label6.Text = "Init";
                            }
                            else
                            {
                                label6.Text = ContempWeight.Weight + "g";
                                if (ContempWeight.IsStable)
                                {
                                    label7.Text = "°";
                                }
                                else
                                {
                                    label7.Text = " ";
                                }
                            }
                        }
                        else if (isZero == 1)
                            label6.Text = "Clearing";
                        else
                        {
                            label6.Text = "ClearFail";
                        }
                    }
                    else
                    {
                        this.BackColor = Color.LightGray;
                        label5.Text = "已关闭";
                    }
                }
            }
            catch(Exception exp)

            {

            }
        }

        private void ANDweigh_ParentChanged(object sender, EventArgs e)
        {
            if (!IsDesignMode)
            {
                if (Parent != null)
                {
                    timer1.Start();
                }
                else
                {
                    timer1.Stop();
                }

                if (this.ParentForm != null)
                {
                    if (IsFormShowType)
                    {
                        ParentForm.FormClosing += new FormClosingEventHandler(ParentForm_FormClosing);
                        ParentForm.AutoSize = true;
                        ParentForm.Text = Name;
                    }
                }
                else
                {

                }
            }
        }

        private  bool IsDesignMode
        {
            get
            {
                bool returnFlag = false;
                if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
                {
                    returnFlag = true;
                }
                else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
                {
                    returnFlag = true;
                }
                return returnFlag;
            }
        }

        private void ParentForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (ParentForm != null)
                ParentForm.Controls.Clear();

        }

        private void panel2_Paint(object sender, PaintEventArgs e)
        {

        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            StableTimes.Value = decimal.ToInt32(numericUpDown1.Value);
        }

        public void FormShow(bool mode)
        {
            if (form != null)
            {
                if (form.IsDisposed)
                {
                    form = null;
                }
                form = null;
            }
            if (form == null)
            {
                form = new Form();

                form.Text = Name;
                form.Size = new Size(Size.Width + 10, Size.Height + 50);
                form.FormClosing += new FormClosingEventHandler(FormClosing);
                //form.SizeChanged += Form_SizeChanged;
                form.Controls.Add(this);
            }
            form.WindowState = FormWindowState.Normal;
            form.MaximizeBox = false;
            form.Activate();
            if (mode)
            {
                form.ShowDialog();
            }
            else
            {
                form.Show();
            }


        }


        public void FormShow(FlowLayoutPanel panel)
        {
            if (form != null)
            {
                if (form.IsDisposed)
                {
                    form = null;
                }
            }
            if (form == null)
            {
                form = new Form();

                form.Text = Name;
                form.Size = new Size(Size.Width + 20, Size.Height + 50);
                form.FormClosing += new FormClosingEventHandler(FormClosing);
                form.Controls.Add(this);
                form.TopLevel = false;
                panel.Controls.Add(form);
            }
            form.WindowState = FormWindowState.Normal;
            form.MaximizeBox = false;
            form.Activate();
            form.Show();
        }

        private void Form_SizeChanged(object sender, EventArgs e)
        {
            this.Size = new Size(form.Width-20, form.Height - 50);
        }

        public void FormShow()
        {
            FormShow(true);
        }

        private void FormClosing(object sender, FormClosingEventArgs e)
        {
            form.Controls.Clear();
        }

    }


}
